package com.yt.util;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.InputStreamBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {
    static RequestConfig REQUEST_CONFIG = RequestConfig.copy(RequestConfig.DEFAULT)
            .setSocketTimeout(60000)
            .setConnectTimeout(10000)
            .setConnectionRequestTimeout(10000)
            .build();


    public static String sendHttpPostRequest(Map<String, Object> paramMap,
                                             String url) {

        Map<String, String> map = Maps.transformValues(paramMap, new Function<Object, String>() {
            public String apply(Object input) {
                return input.toString();
            }
        });
        return sendHttpPostRequest(url, map);

    }

    /**
     * 发送一次post请求
     *
     * @param url
     * @param paramMap
     * @param timeout  请求超时，毫秒数
     * @return
     * @date Mar 8, 2014 4:19:27 PM
     * @author wuzl
     * @comment
     */
    public static String sendHttpPostRequest(String url,
                                             Map<String, String> paramMap, int timeout) {
        try {
            RequestConfig config = RequestConfig.copy(REQUEST_CONFIG)
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(1000)
                    .setConnectionRequestTimeout(1000)
                    .build();
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            if (paramMap != null) {
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    nvps.add(new BasicNameValuePair(paramName, paramMap
                            .get(paramName)));
                }
            }

            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            HttpResponse response = httpClient.execute(httpPost);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一次post请求,默认10秒超时
     *
     * @param url
     * @param paramMap
     * @return
     * @date Mar 8, 2014 4:19:27 PM
     * @author wuzl
     * @comment
     */
    public static String sendHttpPostRequest(String url,
                                             Map<String, String> paramMap) {
        return sendHttpPostRequest(url, paramMap, 10000);
    }

    /**
     * 发送一次get请求带header
     *
     * @param url
     * @param paramMap
     * @return
     */
    public static String sendHttpGetRequest(String url,
                                            Map<String, String> paramMap) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            String paramStr = "";
            if (paramMap != null) {
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    params.add(new BasicNameValuePair(paramName, paramMap
                            .get(paramName)));
                }
                paramStr = EntityUtils
                        .toString(new UrlEncodedFormEntity(params));
            }
            HttpGet httpget = new HttpGet(url + "?" + paramStr);
            HttpResponse response = httpClient.execute(httpget);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一次http请求
     *
     * @param url
     * @return
     */
    public static String sendHttpGetRequest(String url) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            // url = URLEncoder.encode(url,"utf-8");
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpget);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    throw new RuntimeException(EntityUtils.toString(response.getEntity()));
                }
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一次http请求
     *
     * @param url
     * @param timeout 超时时间，毫秒
     * @return
     */
    public static String sendHttpGetRequest(String url, int timeout) {
        try {
            RequestConfig config = RequestConfig.copy(RequestConfig.DEFAULT)
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(10000)
                    .setConnectionRequestTimeout(10000)
                    .build();
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
            // url = URLEncoder.encode(url,"utf-8");
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpget);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    throw new RuntimeException(EntityUtils.toString(response.getEntity()));
                }
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一次get请求带header
     *
     * @param url
     * @param headerMap
     * @param paramMap
     * @return
     */
    public static String sendHttpGetRequestAndHeader(String url,
                                                     Map<String, String> headerMap, Map<String, String> paramMap) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            String paramStr = "";
            if (paramMap != null) {
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    params.add(new BasicNameValuePair(paramName, paramMap
                            .get(paramName)));
                }
                paramStr = EntityUtils
                        .toString(new UrlEncodedFormEntity(params));
            }
            HttpGet httpget = new HttpGet(url + "?" + paramStr);
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpget.setHeader(entry.getKey(), entry.getValue());
                }
            }
            HttpResponse response = httpClient.execute(httpget);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    return EntityUtils.toString(response.getEntity());
                }
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一个带文件的post请求
     *
     * @param url
     * @param paramMap
     * @param fileParamMap
     * @return
     */
    public static String sendHttpPostRequestHaveFile(String url,
                                                     Map<String, String> paramMap, Map<String, File> fileParamMap) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.DEFAULT).build();
            HttpPost httpPost = new HttpPost(url);
            MultipartEntity reqEntity = new MultipartEntity();
            if (paramMap != null) {
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    reqEntity.addPart(
                            paramName,
                            new StringBody(paramMap.get(paramName), Charset
                                    .forName("UTF-8")));
                }
            }
            if (fileParamMap != null) {
                // 循环加入请求文件参数
                for (String fileName : fileParamMap.keySet()) {
                    reqEntity.addPart(fileName,
                            new FileBody(fileParamMap.get(fileName)));
                }
            }
            httpPost.setEntity(reqEntity);
            HttpResponse response = httpClient.execute(httpPost);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一个带文件的post请求
     *
     * @param url
     * @param paramMap
     * @param fileParamMap
     * @return
     */
    public static String sendHttpPostRequestHaveFileInputStream(String url,
                                                                Map<String, String> paramMap, Map<String, InputStream> fileParamMap) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.DEFAULT).build();
            HttpPost httpPost = new HttpPost(url);
            MultipartEntity reqEntity = new MultipartEntity();
            if (paramMap != null) {
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    reqEntity.addPart(
                            paramName,
                            new StringBody(paramMap.get(paramName), Charset
                                    .forName("UTF-8")));
                }
            }
            if (fileParamMap != null) {
                // 循环加入请求文件参数
                for (String fileName : fileParamMap.keySet()) {
                    reqEntity.addPart(fileName, new InputStreamBody(
                            fileParamMap.get(fileName), fileName));
                }
            }
            httpPost.setEntity(reqEntity);
            HttpResponse response = httpClient.execute(httpPost);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一个post请求，带有header
     *
     * @param url
     * @param headerMap
     * @param paramMap
     * @return
     */
    public static String sendHttpPostRequestAndHeader(String url,
                                                      Map<String, String> headerMap, Map<String, String> paramMap) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            HttpPost httpPost = new HttpPost(url);
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            if (paramMap != null) {
                // 循环加入请求参数
                for (String paramName : paramMap.keySet()) {
                    nvps.add(new BasicNameValuePair(paramName, paramMap
                            .get(paramName)));
                }
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            HttpResponse response = httpClient.execute(httpPost);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    return EntityUtils.toString(response.getEntity());
                }
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一个post json请求，带有header
     *
     * @param url
     * @param headerMap
     * @param obj       请求参数
     * @return
     */
    public static String sendHttpJsonPostRequestAndHeader(String url,
                                                          Map<String, String> headerMap, Object obj) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            HttpPost httpPost = new HttpPost(url);
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            StringEntity entity = new StringEntity(JSON.toJSONString(obj),
                    "utf-8");// 解决中文乱码问题
            entity.setContentEncoding("UTF-8");
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);
            if (!(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK)) {
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    return EntityUtils.toString(response.getEntity());
                }
                throw new RuntimeException("服务器异常稍后再试:" + url + ";" + EntityUtils.toString(response.getEntity()));
            }
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 发送一次http请求 接收错误码
     *
     * @param url
     * @return
     */
    public static String sendHttpGetRequestHvaeCode(String url) {
        try {
            HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
            // url = URLEncoder.encode(url,"utf-8");
            HttpGet httpget = new HttpGet(url);
            HttpResponse response = httpClient.execute(httpget);
            return EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}